#include "StdAfx.h"
#define _CRT_SECURE_NO_DEPRECATE
#include "filelog.h"
#include "../../../include/safestropt.h"

CFileLog::CFileLog(void)
{
}

CFileLog::~CFileLog(void)
{
}

bool CFileLog::Init( const char* pszDir, const char* pszLogFileName )
{
    char szFile[PATH_MAX];

    m_flag = LOG_LEVEL_NONE;

    StrSafeCopy(m_szDir, pszDir);
    StrSafeCopy(m_szFileName, pszLogFileName);

    if (!__MkDir(pszDir))
    {
        return false;
    }

    time_t now = time(NULL);
    struct tm current_time = *localtime(&now);

#ifdef _WIN32
    SafeSprintf(szFile, "%s/%s%04d-%02d-%02d.txt", m_szDir, m_szFileName, current_time.tm_year+1900, current_time.tm_mon+1, current_time.tm_mday, m_index);
#else
    snprintf(szFile, sizeof(szFile), "%s/%s%04d-%02d-%02d.txt",
        m_szDir, m_szFileName,
        current_time.tm_year+1900, current_time.tm_mon+1, current_time.tm_mday, m_index);
#endif

    m_pFile = fopen(szFile, "a");

    if (!m_pFile)
    {
        return false;
    }

    m_index = 0;
    m_Time = current_time;

    return m_log_thread.Start();
}

void CFileLog::UnInit( void )
{
    m_log_thread.Stop();

    if (m_pFile)
    {
        fclose(m_pFile);
        m_pFile = NULL;
    }
}

void CFileLog::OpenLevel( ELogLevel eLogLV )
{
    m_flag = m_flag|eLogLV;
}

void CFileLog::CloseLevel( ELogLevel eLogLV )
{
    m_flag &= ~eLogLV;
}

bool CFileLog::IsLevelOpen( ELogLevel eLogLV )
{
    return m_flag & eLogLV ? true:false;
}

void CFileLog::Flush( void )
{
    m_need_flush = true;
}

void CFileLog::Release( void )
{
    UnInit();
    delete this;
}

bool CFileLog::__MkDir( const char* pszDir )
{
    char szPath[PATH_MAX] = {0};
    strncpy(szPath, pszDir, PATH_MAX);
    char* p1 = szPath+1;

    char* p = szPath;

    for (size_t i = 0; i < strlen(szPath); i++)
    {
        if (*(p+i) == '\\')
        {
            *(p+i) ='/';
        }
    }

    do 
    {
        p1 = strchr(p1, '/');
        if (p1 != NULL)
        {
            *p1 = '\0';
        }
#ifdef _WIN32
        if (-1 == _mkdir(szPath))
#else
        if (-1 == mkdir(szPath, 0755))
#endif

        {
            if ((NULL == p1)&&(errno != EEXIST))
            {
                return false;
            }
        }
        if (p1 != NULL)
        {
            *p1++ = '/';
        }

    } while(p1 != NULL);

    return true;
}

void CFileLog::__CheckLog( void )
{
    char szFile[PATH_MAX];
    time_t now = time(NULL);
    struct tm current_time = *localtime(&now);

    if (m_pFile)
    {
        while (ftell(m_pFile) >= MAX_LOGFILE_SIZE)
        {
            m_index++;

#ifdef _WIN32
            SafeSprintf(szFile, "%s/%s%04d-%02d-%02d(%d).txt", m_szDir, m_szFileName, current_time.tm_year+1900, current_time.tm_mon+1, current_time.tm_mday, m_index);
#else
            snprintf(szFile, sizeof(szFile), "%s/%s%04d-%02d-%02d(%d).txt",
                m_szDir, m_szFileName,
                current_time.tm_year+1900, current_time.tm_mon+1, current_time.tm_mday, m_index);
#endif

            fclose(m_pFile);
            m_pFile = fopen(szFile, "a");
        }
    }

    if (m_Time.tm_year != current_time.tm_year
        || m_Time.tm_mon != current_time.tm_mon
        || m_Time.tm_mday != current_time.tm_mday)
    {
#ifdef _WIN32
        SafeSprintf(szFile, "%s/%s%04d-%02d-%02d(%d).txt", m_szDir, m_szFileName, current_time.tm_year+1900, current_time.tm_mon+1, current_time.tm_mday, m_index);
#else
        snprintf(szFile, sizeof(szFile), "%s/%s%04d-%02d-%02d(%d).txt",
            m_szDir, m_szFileName,
            current_time.tm_year+1900, current_time.tm_mon+1, current_time.tm_mday, m_index);
#endif
        if (m_pFile)
        {
            fclose(m_pFile);
        }
        m_pFile = fopen(szFile, "a");
        m_index = 0;
    }

    m_Time = current_time;
}

void CFileLog::Write( const char* pszLog, bool log_console )
{
    __CheckLog();

    fprintf(m_pFile, "%04d-%02d-%02d %02d:%02d:%02d %s\r\n",
        m_Time.tm_year+1900, m_Time.tm_mon+1, m_Time.tm_mday,
        m_Time.tm_hour, m_Time.tm_min, m_Time.tm_sec, pszLog);

    if (log_console)
        printf("%04d-%02d-%02d %02d:%02d:%02d %s\r\n",
        m_Time.tm_year+1900, m_Time.tm_mon+1, m_Time.tm_mday,
        m_Time.tm_hour, m_Time.tm_min, m_Time.tm_sec, pszLog);
}

void CFileLog::FlushLog( void )
{
    if (m_pFile)
    {
        fflush(m_pFile);
        m_need_flush = false;
    }
}

//bool CFileLog::Log( ELogLevel eLogLV, const char* szFormat, ... )
//{
//    if (!szFormat)
//    {
//        return false;
//    }
//
//    log_data_head* head = (log_data_head*)m_log_buff;
//    head->log = this;
//
//    char* ptr = m_log_buff+sizeof(log_data_head);
//
//    switch (eLogLV)
//    {
//    case LOG_LEVEL_CRI:
//        {
//            if (!(m_flag&LOG_LEVEL_CRI))
//            {
//                return false;
//            }
//
//            strcpy(ptr, "[CRI] ");
//            head->log_level = LOG_LEVEL_CRI;
//        }
//    	break;
//    case LOG_LEVEL_WRN:
//        {
//            if (!(m_flag&LOG_LEVEL_WRN))
//            {
//                return false;
//            }
//
//            strcpy(ptr, "[WRN] ");
//            head->log_level = LOG_LEVEL_WRN;
//        }
//        break;
//    case LOG_LEVEL_INF:
//        {
//            if (!(m_flag&LOG_LEVEL_INF))
//            {
//                return false;
//            }
//
//            strcpy(ptr, "[INF] ");
//            head->log_level = LOG_LEVEL_INF;
//        }
//        break;
//    case LOG_LEVEL_DBG:
//        {
//            if (!(m_flag&LOG_LEVEL_DBG))
//            {
//                return false;
//            }
//
//            strcpy(ptr, "[DBG] ");
//            head->log_level = LOG_LEVEL_DBG;
//        }
//        break;
//    default:
//        return false;
//    }
//
//    size_t pre = strlen(ptr);
//
//    va_list args;
//    va_start(args, szFormat);
//#ifdef _WIN32
//    _vsnprintf_s(ptr + pre, sizeof(m_log_buff)-pre-sizeof(log_data_head), _TRUNCATE, szFormat, args);
//#endif
//
//    head->data_len = strlen(ptr);
//
//    return m_log_thread.PushLogData(m_log_buff, sizeof(log_data_head)+head->data_len);
//}

bool CFileLog::LogCri( const char* szFormat, ... )
{
    if (!szFormat)
    {
        return false;
    }

    m_log_lock.Lock();

    log_data_head* head = (log_data_head*)m_log_buff;
    head->log = this;

    char* ptr = m_log_buff+sizeof(log_data_head);

    if (!(m_flag&LOG_LEVEL_CRI))
    {
        return false;
    }

    strcpy(ptr, "[CRI] ");
    head->log_level = LOG_LEVEL_CRI;

    size_t pre = strlen(ptr);

    va_list args;
    va_start(args, szFormat);
#ifdef _WIN32
    _vsnprintf_s(ptr + pre, sizeof(m_log_buff)-pre-sizeof(log_data_head), _TRUNCATE, szFormat, args);
#endif

    head->data_len = strlen(ptr);

    bool ret = m_log_thread.PushLogData(m_log_buff, sizeof(log_data_head)+head->data_len);

    m_log_lock.UnLock();

    return ret;
}

bool CFileLog::LogWrn( const char* szFormat, ... )
{
    if (!szFormat)
    {
        return false;
    }

    m_log_lock.Lock();

    log_data_head* head = (log_data_head*)m_log_buff;
    head->log = this;

    char* ptr = m_log_buff+sizeof(log_data_head);

    if (!(m_flag&LOG_LEVEL_WRN))
    {
        return false;
    }

    strcpy(ptr, "[WRN] ");
    head->log_level = LOG_LEVEL_WRN;

    size_t pre = strlen(ptr);

    va_list args;
    va_start(args, szFormat);
#ifdef _WIN32
    _vsnprintf_s(ptr + pre, sizeof(m_log_buff)-pre-sizeof(log_data_head), _TRUNCATE, szFormat, args);
#endif

    head->data_len = strlen(ptr);

    bool ret = m_log_thread.PushLogData(m_log_buff, sizeof(log_data_head)+head->data_len);

    m_log_lock.UnLock();

    return ret;
}

bool CFileLog::LogInf( const char* szFormat, ... )
{
    if (!szFormat)
    {
        return false;
    }

    m_log_lock.Lock();

    log_data_head* head = (log_data_head*)m_log_buff;
    head->log = this;

    char* ptr = m_log_buff+sizeof(log_data_head);

    if (!(m_flag&LOG_LEVEL_INF))
    {
        return false;
    }

    strcpy(ptr, "[INF] ");
    head->log_level = LOG_LEVEL_INF;

    size_t pre = strlen(ptr);

    va_list args;
    va_start(args, szFormat);
#ifdef _WIN32
    _vsnprintf_s(ptr + pre, sizeof(m_log_buff)-pre-sizeof(log_data_head), _TRUNCATE, szFormat, args);
#endif

    head->data_len = strlen(ptr);

    bool ret = m_log_thread.PushLogData(m_log_buff, sizeof(log_data_head)+head->data_len);

    m_log_lock.UnLock();

    return ret;
}

bool CFileLog::LogDbg( const char* szFormat, ... )
{
    if (!szFormat)
    {
        return false;
    }

    m_log_lock.Lock();

    log_data_head* head = (log_data_head*)m_log_buff;
    head->log = this;

    char* ptr = m_log_buff+sizeof(log_data_head);

    if (!(m_flag&LOG_LEVEL_DBG))
    {
        return false;
    }

    strcpy(ptr, "[DBG] ");
    head->log_level = LOG_LEVEL_DBG;

    size_t pre = strlen(ptr);

    va_list args;
    va_start(args, szFormat);
#ifdef _WIN32
    _vsnprintf_s(ptr + pre, sizeof(m_log_buff)-pre-sizeof(log_data_head), _TRUNCATE, szFormat, args);
#endif

    head->data_len = strlen(ptr);

    bool ret = m_log_thread.PushLogData(m_log_buff, sizeof(log_data_head)+head->data_len);

    m_log_lock.UnLock();

    return ret;
}
